package cn.jx.cjm.codegenerator;

import cn.jx.cjm.codegenerator.base.SqlInfo;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.dom4j.*;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.jx.cjm.codegenerator.SqlBuild.tableModuleMap;

/**
 * @author James Chen right_way@foxmail.com
 * @since 2020/6/2 19:25
 */
public class FileBuild {

    private static TableInfo tableInfoNow;

    public static TableInfo buildBaseFile(SqlInfo sqlinfo, String moduleName, String tableName) {
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath;
        String pagePath;
        if (!CodeGenerator.generateConfig.getDisperseModule()) {
            projectPath = System.getProperty("user.dir") + "/" + CodeGenerator.generateConfig.getProjectPath();
            pagePath = projectPath + "/src/main/resources/templates/pages";
        } else {
            projectPath = System.getProperty("user.dir") + "/keiskei-" + moduleName;
            pagePath = System.getProperty("user.dir") + "/pages";
        }
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor(CodeGenerator.generateConfig.getAuthor());
        gc.setOpen(false);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent(CodeGenerator.generateConfig.getParentPackage());
        pc.setModuleName(moduleName);

        // 自定义模板
        List<FileOutConfig> focList = getFocList(projectPath, pagePath, pc);

        //自定义注入模板参数
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<>(1);
                map.put("cjmModuleName", moduleName);
                map.put("minExport", CodeGenerator.generateConfig.getMingExportNum());
                map.put("tableModuleMap", tableModuleMap);
                map.put("idType", CodeGenerator.generateConfig.getIdType());
                this.setMap(map);
            }
        };
        cfg.setFileOutConfigList(focList);


        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setSuperEntityClass(CodeGenerator.generateConfig.getSupperEntity());
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setInclude(tableName);
        strategy.setSuperEntityColumns(CodeGenerator.generateConfig.getSuperEntityColumns());
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setEntityTableFieldAnnotationEnable(false);
        strategy.setTablePrefix(CodeGenerator.generateConfig.getTablePrefix());

        AutoGenerator mpg = new AutoGenerator();

        mpg.setGlobalConfig(gc);
        mpg.setDataSource(getDataSourceConfig(sqlinfo.getSqlUrl(), sqlinfo.getSqlDriverName(), sqlinfo.getSqlUserName(), sqlinfo.getSqlPassword()));
        mpg.setPackageInfo(pc);
        mpg.setCfg(cfg);
        mpg.setTemplate((new TemplateConfig()).setController("templates/controller/controller.java"));
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();

        return tableInfoNow;
    }

    /**
     * 构建pom 文件
     *
     * @param moduleName 。
     * @throws Exception 。
     */
    public static void buildPomFile(String moduleName) throws Exception {
        // 创建一个XML解析器对象
        SAXReader reader = new SAXReader();
        // 读取XML文档，返回Document对象
        Document document = reader.read(new File(System.getProperty("user.dir") + "/pom.xml"));
        // 创建一个XMLWriter对象
        OutputFormat format = OutputFormat.createPrettyPrint();
        XMLWriter parentWriter = new XMLWriter(new FileOutputStream(System.getProperty("user.dir") + "/pom.xml"), format);

        // 获取根元素节点
        Element root = document.getRootElement();
        root.element("modules").addElement("module").setText(moduleName);

        parentWriter.write(document);

        String parentGroupId = root.element("groupId").getText();
        String parentArtifactId = root.element("artifactId").getText();
        String parentVersion = root.element("version").getText();
        Namespace pomNamespace = root.getNamespace();
        List<Attribute> rootAttributes = new ArrayList<>();
        for (int i = 0; i < root.attributeCount(); i++) {
            rootAttributes.add(root.attribute(i));
        }
        Element artifactIdDom = root.element("artifactId").createCopy();
        Element versionDom = root.element("version").createCopy();

        Element parentDom = root.element("parent").createCopy();
        Element repositoriesDom = root.element("repositories").createCopy();
        Element modelVersionDom = root.element("modelVersion").createCopy();

        // 创建一个XMLWriter对象
        File file = new File(System.getProperty("user.dir") + "/" + moduleName + "/pom.xml");
        XMLWriter writer = new XMLWriter(new FileOutputStream(file), format);
        // 生成一个新的Document对象
        Document doc = DocumentHelper.createDocument();
        Element projectDom = doc.addElement("project");
        projectDom.addNamespace(pomNamespace.getPrefix(), pomNamespace.getURI());
        projectDom.setAttributes(rootAttributes);

        projectDom.add(modelVersionDom);

        parentDom.element("groupId").setText(parentGroupId);
        parentDom.element("artifactId").setText(parentArtifactId);
        parentDom.element("version").setText(parentVersion);

        artifactIdDom.setText(moduleName);
        versionDom.setText(parentVersion);


        projectDom.add(parentDom);
        projectDom.add(artifactIdDom);
        projectDom.add(versionDom);
        projectDom.add(repositoriesDom);


        writer.write(doc);

    }

    /**
     * 自定义模板
     *
     * @param pc          包配置
     * @return .
     */
    private static List<FileOutConfig> getFocList(String projectPath, String pagePath, PackageConfig pc) {
        List<FileOutConfig> focList = new ArrayList<>();


        focList.add(new FileOutConfig("/templates/pages/views/page.vue.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return pagePath + "/src/views/" + pc.getModuleName() + "/" + CodeGenerator.processEntityName(tableInfo.getEntityName()) + "/index.vue";
            }
        });
        focList.add(new FileOutConfig("/templates/pages/api/api.js.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                tableInfoNow = tableInfo;
                return pagePath + "/src/api/" + pc.getModuleName() + "/" + CodeGenerator.processEntityName(tableInfo.getEntityName()) + ".js";
            }
        });
        for (Map.Entry<String, String> entry : CodeGenerator.TEMPLATES.entrySet()) {
            focList.add(new FileOutConfig("/templates/" + entry.getValue() + StringUtils.firstToLowerCase(entry.getKey()) + ".java.ftl") {
                @Override
                public String outputFile(TableInfo tableInfo) {
                    return projectPath + "/src/main/java/cn/jx/cjm/" + pc.getModuleName() + "/" + entry.getValue() + tableInfo.getEntityName() + entry.getKey() + StringPool.DOT_JAVA;
                }
            });
        }

        return focList;
    }

    /**
     * 数据源配置
     *
     * @param sqlUrl        数据库连接
     * @param sqlDriverName 驱动名称
     * @param sqlUsername   用户名
     * @param sqlPassword   密码
     * @return .
     */
    private static DataSourceConfig getDataSourceConfig(String sqlUrl, String sqlDriverName, String sqlUsername, String sqlPassword) {
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(sqlUrl);
        dsc.setDriverName(sqlDriverName);
        dsc.setUsername(sqlUsername);
        dsc.setPassword(sqlPassword);
        return dsc;
    }


}
